/**
 * Copyright 2013 opencxa.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * @author Christopher Armenio
 */


// ******** includes ********
#include <cxa_assert.h>
#include <cxa_delay.h>
#include <cxa_logger_implementation.h>
#include <cxa_xmega_clockController.h>
#include <cxa_xmega_gpio.h>
#include <cxa_xmega_pmic.h>
#include <cxa_xmega_timeBase.h>
#include <cxa_xmega_timer32.h>
#include <cxa_xmega_usart.h>

#include <cxa_serial_protocolParser.h>
#include <cxa_serial_rpcProtocolManager.h>


// ******** local macro definitions ********


// ******** local type definitions ********


// ******** local function prototypes ********
static void initSystem(void);
static bool reqCb(cxa_fixedByteBuffer_t *const dataBytesIn, cxa_fixedByteBuffer_t *const responseBytesOut, void *const userVarIn);


// ********  local variable declarations *********
static cxa_xmega_usart_t usart_debug;
static cxa_xmega_usart_t usart_radio;

static cxa_xmega_timer32_t timer;
static cxa_xmega_timeBase_t timeBase;

static cxa_serial_rpcProtocolManager_t rpcMan;


// ******** local function implementations ********
int main(void)
{
	initSystem();
	printf("\r\n\r\ninitialized\r\n");
	
	cxa_serial_rpcProtocolManager_init(&rpcMan, &timeBase.super);
	cxa_serial_rpcProtocolManager_start(&rpcMan, cxa_usart_getFileDescriptor(&usart_radio.super));
	cxa_serial_rpcProtocolManager_addRequestListener(&rpcMan, 0x01, reqCb, NULL);
	
	while(1)
	{
		cxa_serial_rpcProtocolManager_update(&rpcMan);
	}
}


static void initSystem(void)
{
	cxa_xmega_pmic_init();
	cxa_xmega_pmic_enableInterruptLevel(CXA_XMEGA_PMIC_INTLEVEL_LOW);
	cxa_xmega_pmic_enableInterruptLevel(CXA_XMEGA_PMIC_INTLEVEL_MED);
	cxa_xmega_pmic_enableInterruptLevel(CXA_XMEGA_PMIC_INTLEVEL_HIGH);
	
	// set our clock speed
	cxa_xmega_clockController_init(CXA_XMEGA_CC_INTOSC_32MHZ);
	
	// set our assert GPIO
	//cxa_assert_setAssertGpio(&gpio_led_statRed.super);
	
	// setup our debug USART
	cxa_xmega_usart_init_noHH(&usart_debug, &USARTE0, 9600);
	stdout = stdin = stderr = cxa_usart_getFileDescriptor(&usart_debug.super);
	cxa_assert_setFileDescriptor(stderr);
	cxa_logger_setGlobalFd(stdout);
	
	cxa_xmega_usart_init_noHH(&usart_radio, &USARTC0, 9600);
	
	// setup our 32-bit timer and corresponding timeBase
	cxa_xmega_timer32_init_freerun(&timer, CXA_XMEGA_TIMER16_TCC0, CXA_XMEGA_TIMER16_TCC1, CXA_XMEGA_TIMER16_CLOCKSRC_PERCLK_DIV1024);
	cxa_xmega_timeBase_init_timer32(&timeBase, &timer);
	
	
	// aaaannnndddd....GO!
	cxa_xmega_pmic_enableGlobalInterrupts();
}


static bool reqCb(cxa_fixedByteBuffer_t *const dataBytesIn, cxa_fixedByteBuffer_t *const responseBytesOut, void *const userVarIn)
{
	cxa_assert(dataBytesIn);
	
	/*
	printf("\r\nrx: ");
	cxa_fixedByteBuffer_writeToFile_asciiHexRep(dataBytesIn, stdout);
	printf("\r\n");
	*/
	
	cxa_fixedByteBuffer_append_fbb(responseBytesOut, dataBytesIn);
	
	return true;
}